package model;
import java.awt.Color;
import java.util.Iterator;
import java.util.List;

/**
 * A simple model of a rabbit.
 * Rabbits age, move, breed, and die.
 * 
 * @author Arjan Frans, Alwin Rombout, Jelte Verbree, Brendan Kanters
 * @version 1.0
 */
public class Rabbit extends Animal
{
    // Characteristics shared by all rabbits (static fields).

    // The age at which a rabbit can start to breed.
    private static int BREEDING_AGE;
    // The age to which a rabbit can live.
    private static int MAX_AGE;
    // The likelihood of a rabbit breeding.
    private static double breedingProbability;
    // The maximum number of births.
    private static int maxLitterSize;
    
    private int currentLitterSize;
    
    private static int GRASS_FOOD_VALUE;
    
	private Color color = Color.yellow;
	
	private static Double GRASS_INFECTION_CHANCE;
	
	private boolean ziekteGen;
   
    
    // Individual characteristics (instance fields).
    

    /**
     * Create a new rabbit. A rabbit may be created with age
     * zero (a new born) or with a random age. This constructer creates a
     * rabbit with a randomized gene.
     * 
     * @param randomAge If true, the rabbit will have a random age.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Rabbit(boolean randomAge, Field field, Location location)
    {
        super(field, location);
        
        if(randomAge) {
            age = rand.nextInt(MAX_AGE);
            foodLevel = rand.nextInt(GRASS_FOOD_VALUE);
            currentLitterSize = rand.nextInt(maxLitterSize);;
        }
        else {
        	age = 0;
        	foodLevel = GRASS_FOOD_VALUE;
        	currentLitterSize = maxLitterSize;
        }
        if(rand.nextDouble() <= ZIEKTE_GEN_CHANCE){
        	ziekteGen = true;
        }
        else {
        	ziekteGen = false;
        }
        
    }
    /**
     * Create a new rabbit. A rabbit may be created with age
     * zero (a new born) or with a random age. This constructer creates a
     * rabbit with a given gene, used for birthing rabbits of the same genepool.
     * 
     * @param randomAge If true, the rabbit will have a random age.
     * @param field The field currently occupied.
     * @param location The location within the field.
     * @param ziekteGen The gene making the rabbit susceptible to the virus
     */
    public Rabbit(boolean randomAge, Field field, Location location, boolean ziekteGen)
    {
        super(field, location);
        
        if(randomAge) {
            age = rand.nextInt(MAX_AGE);
            foodLevel = rand.nextInt(GRASS_FOOD_VALUE);
            currentLitterSize = maxLitterSize;
        }
        else {
        	age = 0;
        	foodLevel = GRASS_FOOD_VALUE;
        	currentLitterSize = 0;
        }
        this.ziekteGen = ziekteGen;
        
    }
    
    /**
     * This is what the rabbit does most of the time - it runs 
     * around. Sometimes it will breed or die of old age.
     * @param newRabbits A list to add newly born rabbits to.
     */
    public void act(List<Actor> newRabbits)
    {
    	super.incrementZiekte();
        super.incrementAge();
        incrementHunger();
        if(isZiek){
        	color = Color.red;
        }
        else if(ziekteGen) {
        	color = Color.orange;
        }
        
        else {
        	color = Color.yellow;
        }
        if(isAlive()) {
            giveBirth(newRabbits);            
            // Move towards a source of food if found.
            Location location = getLocation();
            Location newLocation = findGrass(location);
            if(newLocation == null) {
            	newLocation = getField().freeAdjacentLocation(location);
            }
            if(newLocation != null) {
                setLocation(newLocation);
            }
            else {
                // Overcrowding.
                setDead();
                return;
            }
            infect();
        }
    }

    /**
     * get the location of the grass
     * @param location
     * @return where the grass is
     */
    private Location findGrass(Location location)
    {
    	Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
        while(it.hasNext()) {
            Location where = it.next();
            Object obj = field.getGrassAt(where);
            if(obj != null && field.getObjectAt(where) == null) {
                Grass grass = (Grass) obj;
                if(grass.isAlive()) { 
                	if(rand.nextDouble() <= GRASS_INFECTION_CHANCE && getZiekteGen()){
                		setIsZiek(true);
                	}
                    grass.setDead();
                    currentLitterSize = maxLitterSize;
                    foodLevel = GRASS_FOOD_VALUE;
                    // Remove the dead grass from the field.
                    field.clearGrass(where);
                    return where;
                }
                
            }
            else {
            	if(currentLitterSize > 0) currentLitterSize--;
            	return where;
            }
        }
        return null;
    }
        

    
    /**
     * @return Max age of a rabbit
     */
	public int getMaxAge() {
		return MAX_AGE;
	}

    /**
     * @return Age of a rabbit that can breed
     */
	public int getBreedingAge() {
		return BREEDING_AGE;
	}

	/**
	 * @return the breedingprobability
	 */
	public double getBreedingProbability() {
		return breedingProbability;
	}

	/**
	 * @return the littersize
	 */
	public int getMaxLitterSize() {
		return currentLitterSize;
	}
	
	/**
	 * 
	 * @param breedingProbabilityRab
	 */
	public static void setBreedingProbability(double breedingProbabilityRab) {
		breedingProbability = breedingProbabilityRab;
	}

	/**
	 * @return the color
	 */
	public Color getColor() {
		return color ;
	}

	/**
	 * set the max litter size
	 * @param maxLitterSizeRab
	 */
	public static void setMaxLitterSize(int maxLitterSizeRab) {
		maxLitterSize = maxLitterSizeRab;		
	}

	/**
	 * set the breeding age
	 * @param breedingAgeRab
	 */
	public static void setBreedingAge(int breedingAgeRab) {
		BREEDING_AGE = breedingAgeRab;		
	}

	/**
	 * set the max age
	 * @param maxAgeRab
	 */
	public static void setMaxAge(int maxAgeRab) {
		MAX_AGE = maxAgeRab;
	}

	/**
	 * 
	 * @return grass food value
	 */
	public static int getGrassFoodValue() {
		return GRASS_FOOD_VALUE;
	}

	/**
	 * set the grass food value
	 * @param gRASS_FOOD_VALUE
	 */
	public static void setGrassFoodValue(int gRASS_FOOD_VALUE) {
		GRASS_FOOD_VALUE = gRASS_FOOD_VALUE;
	}
	
	/**
	 * set the grass infection chance
	 * @param inf
	 */
	public static void setGrassInfection(double inf)
	{
		GRASS_INFECTION_CHANCE = inf;
	}
	
	/**
	 * Returns the the state of the gene making the rabbit susceptible to disease.
	 * @return Ziekte Gen
	 */
	public boolean getZiekteGen()
	{
		return ziekteGen;
	}
	
	/**
	 * set ziekteGen
	 * @param boolean
	 */
	public void setZiekteGen(boolean ziektegen)
	{
		ziekteGen = ziektegen;
	}
	
	/**
	 * set the chance to be born with the disease gene.
	 * @param gen
	 */
	public static void SetZiekteGenChance(double gen)
	{
		ZIEKTE_GEN_CHANCE = gen;
	}
}

